package cron

import (
	"bytes"
	"context"
	"fmt"
	"html/template"
	"net"
	"network-state/controllers/check_telnet"
	"network-state/global"
	"network-state/model"
	"network-state/util"
	"network-state/util/log"
	"network-state/util/mail"
	"sync"
	"time"

	"github.com/gogf/gf/v2/os/gcron"
	"github.com/gogf/gf/v2/os/gctx"
	"github.com/gogf/gf/v2/os/grpool"
	"github.com/gogf/gf/v2/util/gconv"
)

// 检查端口
func CheckTelnet() {

	var (
		err     error
		errInfo string
		ctx     = gctx.New()
		spec    = global.Cfg["CRON_CHECK_TELNET"]
		l       = log.LOG_LEVEL{}
	)

	_, err = gcron.Add(ctx, spec, func(ctx context.Context) {

		// 列表数据
		ct := check_telnet.List()
		TaskTelnet(ct)
	})

	if err != nil {
		errInfo = fmt.Sprintf("CheckUrl 定时任务异常:%v", err)
		l.Log(errInfo)
		panic(err)
	}
}

// 协程任务
func TaskTelnet(i interface{}) {

	var (
		errInfo string
		ctx     = gctx.New()
		wg      = sync.WaitGroup{}
		l       = log.LOG_LEVEL{}
	)

	cu, ok := i.([]model.CheckTelnet)
	if !ok {
		errInfo = fmt.Sprintf("断言失败,协程任务:任务参数类型错误:%v", ok)
		l.Log(errInfo)
		return
	}

	for _, v := range cu {

		wg.Add(1)

		mc := v
		grpool.Add(ctx, func(ctx context.Context) {

			// telnet 检测
			result := telnet(mc)

			if result == "failed" {
				var (
					name = mc.Name
					host = mc.Host + ":" + gconv.String(mc.Port)
				)
				settingMailTelnet(name, host, result)
			}

			wg.Done()
		})

		// go func(mc model.CheckTelnet) {
		// 	getCurl(mc)
		// 	wg.Done()
		// }(v)
	}

	wg.Wait()

}

// 检测连通性, ip地址,
func telnet(i interface{}) string {

	var (
		errInfo string
		result  = "failed"
		l       = log.LOG_LEVEL{}
	)

	ct, ok := i.(model.CheckTelnet)
	if !ok {
		errInfo = fmt.Sprintf("断言失败,检测连通性:任务参数类型错误:%v", ok)
		l.Log(errInfo)
		return "failed"
	}

	address := net.JoinHostPort(ct.Host, gconv.String(ct.Port))

	// 3 秒超时
	conn, err := net.DialTimeout("tcp", address, 3*time.Second)
	if err != nil {
		result = "failed"
	} else {
		if conn != nil {
			result = "success"
			_ = conn.Close()
		} else {
			result = "failed"
		}
	}

	return result
}

/*
设置发送邮件
*/
func settingMailTelnet(name, host, state string) error {

	var (
		errInfo string
		l       = log.LOG_LEVEL{}
	)

	// 读取 html 模板文件
	byteData, err := global.HtmlTemp.ReadFile("templates/check_telnet.html")
	if err != nil {
		errInfo = fmt.Sprintf("读取 check_telnet.html 模板文件失败:%v", err)
		l.Log(errInfo)
	}

	t := template.Must(template.New("").Parse(string(byteData)))

	// 作为变量传递给html模板
	body := new(bytes.Buffer)
	t.Execute(body, struct {
		Name  string
		Host  string
		State string
		Date  string
	}{
		Name:  name,
		Host:  host,
		State: state,
		Date:  util.GetDate(),
	})

	b := body.Bytes()
	html := string(b)

	// 发送邮件
	options := &mail.Options{
		MailHost: global.Cfg["MAIL_HOST"],
		MailPort: gconv.Int(global.Cfg["MAIL_PORT"]),
		MailUser: global.Cfg["MAIL_USER"],
		NickName: name,
		MailPass: global.Cfg["MAIL_PASS"],
		MailTo:   "1@qq.com",
		Subject:  name + " " + util.GetDate(),
		Body:     html,
	}

	err = options.Send()
	return err

}
